package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import com.google.common.base.Strings;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.BaseProcessService;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.UserInfoHandleProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.CommentTypeEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowEntrustQueryForComputeVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowEntrustVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.monitor.FlowTaskTraceVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.EntrustTaskVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.TaskCandidateQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskEntrustService;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskTraceRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTurnTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class FlowTaskEntrustServiceImpl extends BaseProcessService implements FlowTaskEntrustService {

    @Autowired
    private UserInfoHandleProcessor userInfoHandleProcessor;

    @Autowired
    private FlowTaskTraceRepository flowTaskTraceRepository;

    @Autowired
    private TaskService taskService;

    @Autowired
    private FlowTaskServiceImpl flowTaskService;

    @Autowired
    private FlowEntrustRepositoryImpl flowEntrustRepository;

    @Autowired
    private FlowTurnTaskService flowTurnTaskService;

    /**
     * 新任务委托
     * 任务委托仅处理候选人任务，对于组任务、角色人物这些类型的待办暂不处理
     *
     * @param taskEntity
     * @return
     */
    @Override
    public ResponseResult entrustTask(TaskEntity taskEntity) {

        if (Objects.isNull(taskEntity) || Objects.isNull(taskEntity.getProcessDefinitionId()) || Objects.isNull(taskEntity.getIdentityLinks())) {
            return ResponseResult.success();
        }
        String modelKey = taskEntity.getProcessDefinitionId().split(":")[0];
        taskEntity.getIdentityLinks().forEach(link -> {
            if(StringUtils.isNotEmpty(link.getUserId())) {
                log.info("新建待办委托，入参：{}",link);
                EntrustTaskVo entrustTaskVo = new EntrustTaskVo(link.getUserId(), modelKey);
                entrustNewTask(entrustTaskVo);
                if (StringUtils.isNotEmpty(entrustTaskVo.getEntrustToUserCode())) {
                    link.setGroupId(null);
                    link.setUserId(entrustTaskVo.getEntrustToUserCode());
                    log.info("新建待办委托，出参：{}",link);
                    taskService.addComment(taskEntity.getId(), taskEntity.getProcessInstanceId(), "entrustTask", entrustTaskVo.getComment());

                }
            }
        });
        return ResponseResult.success(taskEntity);

    }

    /**
     * 已生成的待办任务委托
     * 任务委托仅处理候选人任务，对于组任务、角色人物这些类型的待办暂不处理
     *
     * @param entrustTaskVo
     * @return
     */
    @Override
    public ResponseResult entrustTodoTask(EntrustTaskVo entrustTaskVo) {

//        根据委托人及流程ID找出待委托任务记录,对已生成的待办任务进行委托处理
        List<FlowTaskTraceVo> result = getTaskByUserCodeAndModelKey(entrustTaskVo.getModelKey(), entrustTaskVo.getClient());
        log.info("已产生待办委托，入参：{}",entrustTaskVo);
        //处理每条任务的委托
        if (Objects.isNull(result)) {
            return ResponseResult.success();
        } else {
            result.forEach(item -> {
                Task task = taskService.createTaskQuery().taskId(item.getTaskId()).singleResult();
                this.addComment(task.getId(), entrustTaskVo.getClient(), task.getProcessInstanceId(), CommentTypeEnum.WT.getName(), entrustTaskVo.getComment());
                //1.转办
                taskService.setAssignee(item.getTaskId(), entrustTaskVo.getEntrustToUserCode());
                taskService.setOwner(item.getTaskId(), entrustTaskVo.getClient());

                //如果在转办之前的操作是委派，则更新委派任务的处理人为转办后的人

                String parentTaskId = task.getParentTaskId();
                if (StringUtils.isNoneBlank(parentTaskId)) {
                    Task parentTask = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                    if (Objects.nonNull(parentTask)) {
                        //更新原委派人为转办后的人
                        parentTask.setAssignee(entrustTaskVo.getEntrustToUserCode());
                        taskService.saveTask(parentTask);
                    }
                }
                //修改转办之后的操作人
                flowTurnTaskService.updateTaskTrace(item.getTaskId(), entrustTaskVo.getEntrustToUserCode(),entrustTaskVo.getClient());
            });
        }
        log.info("已产生待办委托，入参：{}",result);
        return ResponseResult.success(result);
    }

    /**
     * 新任务委托
     * 任务委托仅处理候选人任务，对于组任务、角色人物这些类型的待办暂不处理
     *
     * @param entrustTaskVo
     * @return
     */
    @Override
    public EntrustTaskVo entrustNewTask(EntrustTaskVo entrustTaskVo) {


        // 查看是否存在委托记录
        FlowEntrustQueryForComputeVo flowEntrustQueryForComputeVo=new FlowEntrustQueryForComputeVo();
        BeanUtils.copyProperties(entrustTaskVo,flowEntrustQueryForComputeVo);
        FlowEntrustVo flowEntrustVo = flowEntrustRepository.selectByClientAndModelKey(flowEntrustQueryForComputeVo);
        log.info("查询委托，入参：{}",entrustTaskVo);
        if (!Objects.isNull(flowEntrustVo)) {
            //筛选自定义委托
            if(!Objects.isNull(flowEntrustVo.getFlowEntrustDetailVoList())) {
                flowEntrustVo.getFlowEntrustDetailVoList().forEach(item -> {
                    if (item.getModelKey()==null||item.getModelKey().equals(entrustTaskVo.getModelKey())) {
                        //根据自定义配置，设置被委托人
                        entrustTaskVo.setEntrustToUserCode(item.getTrustee());
                    }
                });
            }
            if (Strings.isNullOrEmpty(entrustTaskVo.getEntrustToUserCode())) {
                //根据默认配置设置被委托人
                entrustTaskVo.setEntrustToUserCode(flowEntrustVo.getTrustee());
            }
            entrustTaskVo.setComment("由用户" + entrustTaskVo.getClient() + "委托至用户"+entrustTaskVo.getEntrustToUserCode());

        }
        log.info("查询委托，出参{}",entrustTaskVo);
        return entrustTaskVo;

    }

    public List<FlowTaskTraceVo> getTaskByUserCodeAndModelKey(String modelKey, String userCode) {
        TaskCandidateQueryVo taskCandidateQueryVo = new TaskCandidateQueryVo();
        if(StringUtils.isNotEmpty(modelKey)) {
            taskCandidateQueryVo.setModelKey(modelKey);
        }

        //如果用户信息不为空，则需要查出来用户信息
        if (StringUtils.isNotBlank(userCode)) {
            userInfoHandleProcessor.convertCandidateQueryVo(taskCandidateQueryVo, userCode);
        }
        List<FlowTaskTraceVo> flowTaskTraceVoList = flowTaskTraceRepository.getFlowTaskByModelAndUser(taskCandidateQueryVo);
        return flowTaskTraceVoList;
    }


}
